package io.fivefire.base.common.service;

import io.fivefire.base.common.domain.entity.BaseEntity;
import io.fivefire.base.common.enums.DataStatusEnum;
import io.fivefire.base.common.enums.OperatorEnum;
import io.fivefire.base.common.enums.SqlOrderEnum;
import io.fivefire.base.common.mapper.BaseMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.ParameterizedType;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

/**
 * @author huijun
 * @date 2018/2/1 上午10:00
 */
public abstract class AbstractBaseService<T extends BaseEntity, M extends BaseMapper<T>> implements IBaseService<T > {

    @Autowired
    private M baseMapper;
    private Class<?> clazz = null;
    protected Class<?> getEntityClass() {
        if (clazz == null) {
            clazz = (Class<?>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return clazz;
    }

    /**
     * 新增一条数据
     *
     * @param entity
     */
    @Override
    public int insert(T entity) {
        enhanceNewCreateBaseEntity(entity, OperatorEnum.INSERT.getDesc());
        return baseMapper.insertSelective(entity);
    }

    /**
     * 修改一条数据
     *
     * @param entity 要更新的实体对象
     */
    @Override
    public int edit(T entity) {
        enhanceNewCreateBaseEntity(entity, OperatorEnum.UPDATE.getDesc());
        return baseMapper.updateByPrimaryKeySelective(entity);
    }

    /**
     * 删除一条数据
     *
     * @param baseEntity
     */
    @Override
    public int delete(T baseEntity) {

        return baseMapper.updateByPrimaryKeySelective(baseEntity);

    }

    /**
     * 删除一条数据
     *
     * @param id
     */
    @Override
    public int delete(Long id, Class<T> clazz) {
        /*Example example = new Example(clazz);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", id);
        criteria.andEqualTo("status", DataStatusEnum.ENABLE.getCode());*/
        T entity = baseMapper.selectByPrimaryKey(id);
        if (entity != null) {
            entity.setStatus(DataStatusEnum.DISABLE.getCode());
            return baseMapper.updateByPrimaryKeySelective(entity);
        }

        return 0;
    }

    /**
     * 更新对象,如果属性为空，则不会进行对应的属性值更新
     *
     * @param entity 要更新的实体对象
     */
    @Override
    public int update(T entity) {
        return baseMapper.updateByPrimaryKeySelective(entity);
    }

    @Override
    public int updateByMap(T entity, Map<String, Object> condition) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andEqualTo(field, condition.get(field));
        }

        return baseMapper.updateByExampleSelective(entity, condition);
    }

    @Override
    public List<T> findList(Map<String, Object> condition) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andEqualTo(field, condition.get(field));
        }
        return baseMapper.selectByExample(example);
    }

    @Override
    public List<T> findList(Map<String, Object> condition, String orderBy, SqlOrderEnum sqlOrderEnum) {

        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andEqualTo(field, condition.get(field));
        }
        if (StringUtils.isNotBlank(orderBy) && sqlOrderEnum != null) {
            if (sqlOrderEnum.getName().equals("desc")) {
                example.orderBy(orderBy).desc();
            } else {
                example.orderBy(orderBy).asc();
            }
        }
        return baseMapper.selectByExample(example);
    }

    /**
     * 根据传入的泛型参数类型查询该类型对应表中的所有数据，返回一个集合对象
     *
     * @return 返回泛型参数类型的对象集合
     */
    @Override
    public List<T> findAll() {
        return baseMapper.selectAll();
    }

    @Override
    public List<T> findAll(String orderBy, SqlOrderEnum sqlOrderEnum) {
        Example example = new Example(getClass());
        if (sqlOrderEnum.getName().equals("desc")) {
            example.orderBy(orderBy).desc();
        } else {
            example.orderBy(orderBy).asc();
        }
        return baseMapper.selectByExample(example);
    }


    /**
     * 根据任意属性和属性值进行对象模糊查询
     *
     * @param condition
     * @return
     */
    @Override
    public List<T> like(Map<String, Object> condition) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andLike(field, (String) condition.get(field));
        }
        return baseMapper.selectByExample(example);
    }

    @Override
    public List<T> like(Map<String, Object> condition, String orderBy, SqlOrderEnum sqlOrderEnum) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andLike(field, (String) condition.get(field));
        }
        if (StringUtils.isNotBlank(orderBy) && sqlOrderEnum != null) {
            if (sqlOrderEnum.getName().equals("desc")) {
                example.orderBy(orderBy).desc();
            } else {
                example.orderBy(orderBy).asc();
            }
        }

        return baseMapper.selectByExample(example);
    }

    /**
     * 根据条件集合进行指定类型单一对象查询
     *
     * @param condition 进行查询的条件集合
     * @return 返回泛型参数类型的对象
     */
    @Override
    public T queryOne(Map<String, Object> condition) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andLike(field, (String) condition.get(field));
        }
        List<T> list = baseMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }

        return null;
    }

    @Override
    public T queryOne(Map<String, Object> condition, String orderBy, SqlOrderEnum sqlOrderEnum) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andLike(field, (String) condition.get(field));
        }

        if (StringUtils.isNotBlank(orderBy) && sqlOrderEnum != null) {
            if (sqlOrderEnum.getName().equals("desc")) {
                example.orderBy(orderBy).desc();
            } else {
                example.orderBy(orderBy).asc();
            }
        }
        List<T> list = baseMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }


    /**
     * 根据条件进行数量的查询
     *
     * @param condition
     * @return 返回符合条件的泛型参数对应表中的数量
     */
    @Override
    public int count(Map<String, Object> condition) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andLike(field, (String) condition.get(field));
        }

        return baseMapper.selectCountByExample(example);
    }

    @Override
    public T selectOne(T entity) {
        return baseMapper.selectOne(entity);
    }

    @Override
    public int updateByExampleSelective(T entity, Map<String, Object> condition) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andLike(field, (String) condition.get(field));
        }
        return baseMapper.updateByExampleSelective(entity, condition);
    }

    /**
     * 根据条件集合进行分页查询
     *
     * @param condition 查询条件
     * @param offset    偏移
     * @param rows      查询条数
     * @return 返回Pager对象
     */
    @Override
    public List<T> listByPage(Map<String, Object> condition, int offset, int rows) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andEqualTo(field, condition.get(field));
        }
        return baseMapper.selectByExampleAndRowBounds(example, new RowBounds(offset, rows));
    }

    @Override
    public List<T> listByPage(Map<String, Object> condition, int offset, int rows, String orderBy, SqlOrderEnum sqlOrderEnum) {
        Example example = new Example(getClass());
        Example.Criteria criteria = example.createCriteria();
        for (String field : condition.keySet()
                ) {
            criteria.andEqualTo(field, condition.get(field));
        }
        if (StringUtils.isNotBlank(orderBy) && sqlOrderEnum != null) {
            if (sqlOrderEnum.getName().equals("desc")) {
                example.orderBy(orderBy).desc();
            } else {
                example.orderBy(orderBy).asc();
            }
        }

        return baseMapper.selectByExampleAndRowBounds(example, new RowBounds(offset, rows));
    }

    private final T enhanceNewCreateBaseEntity(T entity, String operatorType) {
        if (entity instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) entity;
            //设置默认值，如果默认值和common不一样，需要自行设置初始值
            if (baseEntity.getStatus() == null) {
                baseEntity.setStatus(DataStatusEnum.ENABLE.getCode());
            }

            if (operatorType.equals(OperatorEnum.UPDATE.getDesc())) {
                if (baseEntity.getUpdateTime() == null) {
                    baseEntity.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                }
            }else {
                if (baseEntity.getCreateTime() == null) {
                    baseEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
                }
            }

        }

        return entity;
    }


}
